function ConnectionManager(config, dialog){
	var fn = this;
	var isConnect = false;
	var isLogin = false;
	
	fn.connect = function(successCallback, failCallback){
		// Create SmartFox client instance
		fn.sfs = new SmartFox(config);
		fn.addEventListener();
		//connect
		fn.sfs.connect();
		if(successCallback){
			fn.successConnectCallback = successCallback;
		}
		
		if(failCallback){
			fn.failConnectCallback = failCallback;
		}
	},
	
	fn.addEventListener = function(){
		fn.sfs.addEventListener(SFS2X.SFSEvent.CONNECTION, fn.onConnection, this);
		fn.sfs.addEventListener(SFS2X.SFSEvent.CONNECTION_LOST, fn.onConnectionLost, this);
		
		//login and logout event
		fn.sfs.addEventListener(SFS2X.SFSEvent.LOGIN, fn.onLogin, this);
		fn.sfs.addEventListener(SFS2X.SFSEvent.LOGIN_ERROR, fn.onLoginError, this);
		fn.sfs.addEventListener(SFS2X.SFSEvent.LOGOUT, fn.onLogout, this);
		
		//add event room add or remove
		fn.sfs.addEventListener(SFS2X.SFSEvent.ROOM_REMOVE, fn.onRoomRemove, this);
		fn.sfs.addEventListener(SFS2X.SFSEvent.ROOM_ADD, fn.onRoomAdd, this);
		
		//some events when user enters room
		fn.sfs.addEventListener(SFS2X.SFSEvent.USER_ENTER_ROOM, fn.onUserEnterRoom, this);
		fn.sfs.addEventListener(SFS2X.SFSEvent.USER_EXIT_ROOM, fn.onUserExitRoom, this);	
		fn.sfs.addEventListener(SFS2X.SFSEvent.USER_COUNT_CHANGE, fn.onUserCountChange, this);
		fn.sfs.addEventListener(SFS2X.SFSEvent.ROOM_VARIABLES_UPDATE, fn.onRoomVarsUpdate, this);
		//fn.sfs.addEventListener(SFS2X.SFSEvent.USER_VARIABLES_UPDATE, fn.onUserVarsUpdate, this);
		
		fn.sfs.addEventListener(SFS2X.SFSEvent.ROOM_JOIN, fn.onRoomJoined, this);
		fn.sfs.addEventListener(SFS2X.SFSEvent.ROOM_JOIN_ERROR, fn.onRoomJoinError, this);
		
		//some events when user enters new message
		fn.sfs.addEventListener(SFS2X.SFSEvent.PUBLIC_MESSAGE, fn.onPublicMessage, this);
		fn.sfs.addEventListener(SFS2X.SFSEvent.PRIVATE_MESSAGE, fn.onPrivateMessage, this);

        fn.sfs.addEventListener(SFS2X.SFSEvent.EXTENSION_RESPONSE, fn.onExtensionResponse, this);

        fn.sfs.addEventListener(SFS2X.SFSEvent.USER_VARIABLES_UPDATE, fn.onUserVarsUpdate, this);
	},

    fn.onUserVarsUpdate = function(event){
        var changedVars = event.changedVars;
        //var user = event.user;

        //console.log("update value");
		if(fn.onUserVarsUpdateCallback){
			fn.onUserVarsUpdateCallback(event);
		}
    };

    fn.onExtensionResponse = function(event){
        var params = event.params;
        var cmd = event.cmd;

        console.log("======>command "  + cmd);

        switch (cmd){
            case "ready":

                break;
            case "start":

                break;
            case "create_fail":
                fn.onRoomAddError(event);
                break;
            case "join_fail":
                fn.onRoomJoinError(event);
                break;
            case "updateRoom":
                users = params.users;

                if(isDifferent(dataPlayers, users)){
                    dataPlayers = [];
                    for (var i = 0; i < users.length; i++) {
                        var obj = {};
                        obj.name = users[i].name;
                        obj.id = users[i].id;
                        obj.position = users[i].position + 1;
                        obj.isCurrent = users[i].isItMe;
                        //obj.avatar = room.users[i].variables.avatar.value;
                        dataPlayers.push(obj);
                    }

                    if (waitScene != null) {
                        waitScene.addPlayers(dataPlayers);
                    }
                }

                break;
            case "outRoom":
                dataPlayers = [];
                switchView(3);
                //delete waitScene;
                waitScene = new WaitScene();
                var director = cc.Director.getInstance();
                var currentScene = director.getRunningScene();
                if(currentScene.reset){
                    currentScene.reset();
                }
                currentScene.removeAllChildren(true);
                director.replaceScene(waitScene);
                break;
        }
    };
	
	fn.onConnection = function(event){
		if (event.success)
		{
			console.log("Connection succeed");
			isConnect = true;
			if(fn.successConnectCallback){
				fn.successConnectCallback(event.user);
			}
		}
		else
		{
			console.log("Connection failed");
			isConnect = false;
			var error = "Connection failed: " + event.errorMessage;
			dialog.showErrorMessage(I18n["connection failed"]);
			if(fn.failConnectCallback){
				fn.failConnectCallback(event.errorMessage);
			}
		}
	},
	
	fn.onConnectionLost = function(event){
		console.log("connection lost");
		isConnect = false;
		console.log(event.reason);
		dialog.showErrorMessage(I18n["connection lost"]);
	},
	
	fn.login = function(token, successCallback, failCallback){
		if(token != undefined && isConnect && !isLogin){
			fn.successLoginCallback = successCallback;
			fn.failLoginCallback = failCallback;
			fn.sfs.send(new SFS2X.Requests.System.LoginRequest("", "", {"token":token} , GAME_ZONE));
		}
		else if(token == undefined){
			dialog.showErrorMessage(I18n["access denied"]);
		}
		else if(!isConnect){
			dialog.showErrorMessage(I18n["connection failed"]);
		}
		else if(isLogin){
			dialog.showInfoMessage(I18n["you have been login"]);
		}
	},
	
	fn.onLogin = function(event){
		//console.log(event);
		isLogin = true;
		fn.sfs.send(new SFS2X.Requests.System.JoinRoomRequest(LOBBY_ROOM_NAME));
		if(fn.successLoginCallback){
			fn.successLoginCallback(event.user);
		}
	},
	
	fn.onLoginError = function(event){
		dialog.showErrorMessage(I18n["login failed"]);
		if(fn.failLoginCallback){
			fn.failLoginCallback(event);
		}
	},
	
	fn.logout = function(){
			fn.sfs.send(new SFS2X.Requests.System.LogoutRequest());
	},
	
	fn.onLogout = function(){
		isLogin = false;
		window.onbeforeunload = null;
		self.close();
	},
	
	fn.onRoomAdd = function(event){
		if(fn.onRoomAddCallback){
			fn.onRoomAddCallback(event);
		}
	},
	
	fn.onRoomAddError = function(event){
		if(fn.onRoomAddErrorCallback){
			fn.onRoomAddErrorCallback(event);
		}
	},
	
	fn.onRoomRemove = function(event){
		if(fn.onRoomRemoveCallback){
			fn.onRoomRemoveCallback(event);
		}
	},
	
	fn.onRoomJoined = function(event){
		if(fn.onRoomJoinedCallback){
			fn.onRoomJoinedCallback(event);
		}
	},
	
	fn.onRoomJoinError = function(event){
		if(fn.onRoomJoinErrorCallback){
			fn.onRoomJoinErrorCallback(event);
		}
	},
	
	fn.onUserEnterRoom = function(event){
		if(fn.onUserEnterRoomCallback){
			fn.onUserEnterRoomCallback(event);
		}
	},
	
	fn.onUserExitRoom = function(event){
		if(fn.onUserExitRoomCallback){
			fn.onUserExitRoomCallback(event);
		}
	},
	
	fn.onUserCountChange = function(event){
		if(fn.onUserCountChangeCallback){
			fn.onUserCountChangeCallback(event);
		}
	},
	
	fn.onRoomVarsUpdate = function(event){
		if(fn.onRoomUpdateCallback){
			fn.onRoomUpdateCallback(event);
		}
	},
	
	fn.onPublicMessage = function(event){
		if(fn.onPublicMessageCallback){
			fn.onPublicMessageCallback(event);
		}
	},
	
	fn.onPrivateMessage = function(event){
	    console.log("private message");
        console.log(event);
	},
	
	fn.sendPublicMessage = function(message){
		var lobbyRoom = null;
		var joinedRooms = fn.sfs.getJoinedRooms();
		for (var i = 0; i < joinedRooms.length; i++)
		{
			if (joinedRooms[i].name == LOBBY_ROOM_NAME) {
				lobbyRoom = joinedRooms[i];
				break;
			}
		}
		var isSent = fn.sfs.send(new SFS2X.Requests.System.PublicMessageRequest(message, null, lobbyRoom));
		return isSent;
	},
	
	fn.sendPrivateMessage = function(message, roomID){
		var lobbyRoom = null;
		var joinedRooms = fn.sfs.getJoinedRooms();
		for (var i = 0; i < joinedRooms.length; i++)
		{
			if (joinedRooms[i].id == roomID) {
				lobbyRoom = joinedRooms[i];
				break;
			}
		}
		var isSent = fn.sfs.send(new SFS2X.Requests.System.PublicMessageRequest(message, null, lobbyRoom));
		return isSent;
	},
	
	fn.getRoomLists = function(){
		return fn.sfs.roomManager.getRoomList();
	},
	
	fn.createRoom = function(config){
		var isSent = fn.sfs.send( new SFS2X.Requests.System.ExtensionRequest("createMahjongRoom", config));
		return isSent;
	},
	
	fn.joinRoom = function(config){
		var isSent = fn.sfs.send( new SFS2X.Requests.System.ExtensionRequest("joinMahjongRoom", config));
		return isSent;
	},
	
	fn.getConnection = function(){
		return fn.sfs;
	},
	
	fn.setRoomAddCallback = function(callback){
		fn.onRoomAddCallback = callback;
	},
	
	fn.setRoomAddErrorCallback = function(callback){
		fn.onRoomAddErrorCallback = callback;
	},
	
	fn.setRoomRemoveCallback = function(callback){
		fn.onRoomRemoveCallback = callback;
	},
	
	fn.setUserEnterRoomCallback = function(callback){
		fn.onUserEnterRoomCallback = callback;
	},
	
	fn.setUserExitRoomCallback = function(callback){
		fn.onUserExitRoomCallback = callback;
	},
	
	fn.setUserCountChangeCallback = function(callback){
		fn.onUserCountChangeCallback = callback;
	},
	
	fn.setRoomJoinedCallback = function(callback){
		fn.onRoomJoinedCallback = callback;
	},
	
	fn.setRoomJoinErrorCallback = function(callback){
		fn.onRoomJoinErrorCallback = callback;
	},
	
	fn.setRoomUpdateCallback = function(callback){
		fn.onRoomUpdateCallback = callback;
	},
	
	fn.setPublicMessageCallback = function(callback){
		fn.onPublicMessageCallback = callback;
	},
	
	fn.setUserVarsUpdateCallback = function(callback){	
		fn.onUserVarsUpdateCallback = callback;
	}
};